package com.laivi.basic.model.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import com.laivi.basic.common.constants.Constant;
import com.laivi.basic.module.log.Log;
import com.laivi.basic.module.log.Logs;
import com.laivi.basic.type.DBType;
import com.laivi.basic.util.DataUtil;

public class DBPool implements BasicDB{
	private final static Log log=Logs.getLog(DBPool.class);

	private String driver;
	private String url;
	private String user;
	private String password;
	private DBType type;
	
	private int maxConns = 10;
	private int minConns = 5;
	private int currentConns;
	
	private BlockingQueue<Connection> connQueue;
	
	public DBPool(String driver, String url, String user, String password) {
		super();
		this.driver = driver;
		this.url = url;
		this.user = user;
		this.password = password;
		if(url.indexOf("sqlserver")!=-1){
			this.type=DBType.SQLSERVER;
		}else if(url.indexOf("oracle")!=-1){
			this.type=DBType.ORACLE;
		}else if(url.indexOf("hive")!=-1){
			this.type=DBType.HIVE;
		}else{
			this.type=DBType.MYSQL;
		}
		init();
	}
	
	public DBPool(String url, String user, String password,int minConns,int maxConns) {
		super();
		this.url = url;
		this.user = user;
		this.password = password;
		this.minConns=minConns;
		this.maxConns=maxConns;
		if(url.indexOf("sqlserver")!=-1){
			this.type=DBType.SQLSERVER;
			this.driver=Constant.DBDriver.SQLSERVER_JTDS;
		}else if(url.indexOf("oracle")!=-1){
			this.type=DBType.ORACLE;
			this.driver=Constant.DBDriver.ORACLE;
		}else if(url.indexOf("hive")!=-1){
			this.type=DBType.HIVE;
			this.driver=Constant.DBDriver.HIVE;
		}else{
			this.type=DBType.MYSQL;
			this.driver=Constant.DBDriver.MYSQL;
		}
		init();
	}

	public DBPool(String url, String user, String password) {
		super();
		this.url = url;
		this.user = user;
		this.password = password;
		if(url.indexOf("sqlserver")!=-1){
			this.type=DBType.SQLSERVER;
			this.driver=Constant.DBDriver.SQLSERVER_JTDS;
		}else if(url.indexOf("oracle")!=-1){
			this.type=DBType.ORACLE;
			this.driver=Constant.DBDriver.ORACLE;
		}else if(url.indexOf("hive")!=-1){
			this.type=DBType.HIVE;
			this.driver=Constant.DBDriver.HIVE;
		}else{
			this.type=DBType.MYSQL;
			this.driver=Constant.DBDriver.MYSQL;
		}
		init();
	}

	public synchronized void init() {
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			log.error("Database driver not found: " + driver);
		}
		if (minConns > maxConns) {
			minConns = maxConns;
		}
		connQueue = new ArrayBlockingQueue<Connection>(maxConns);
		for (int i = 0; i < minConns; i++) {
			try {
				Connection conn =null;
				if(DataUtil.isEmpty(user)){
					conn = DriverManager.getConnection(url); 
				}else{
					conn = DriverManager.getConnection(url, user, password); 
				}
				connQueue.put(conn);
			} catch (SQLException e) {
				log.error("No database connection");
			} catch (InterruptedException e) {
				log.error(e);
			}
		}
		currentConns=minConns;
	}
	
	public synchronized Connection getConn() {
		try {
			if(connQueue.size()<=0 && currentConns<maxConns){
				if(DataUtil.isEmpty(user)){
					connQueue.put(DriverManager.getConnection(url));
				}else{
					connQueue.put(DriverManager.getConnection(url, user, password));
				}
			}
			return connQueue.take();
		} catch (InterruptedException e) {
			log.error(e);
		} catch (SQLException e) {
			log.error(e);
		}
		return null;
	}
	
	public synchronized void close(Connection conn){
		try {
			if(conn!=null&&connQueue.size()<this.maxConns){
				connQueue.put(conn);
			}else if(conn!=null){
				conn.close();
			}
		} catch (InterruptedException e) {
			log.error(e);
		} catch (SQLException e) {
			
			log.error(e);
		}
	}

	public String getDriver() {
		return driver;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public DBType getType() {
		return type;
	}

	public int getMaxConns() {
		return maxConns;
	}

	public void setMaxConns(int maxConns) {
		this.maxConns = maxConns;
	}

	public int getMinConns() {
		return minConns;
	}

	public void setMinConns(int minConns) {
		this.minConns = minConns;
	}

	@Override
	public String getDataBase() {
		String database=null;
		switch(type){
			case ORACLE:
				database= url.substring(url.lastIndexOf(":")+1, url.length());
				break;
			default:
				database=url.substring(url.lastIndexOf("/")+1, url.length());
				break;
		}
		return database;
	}
}
